diff options
Diffstat (limited to 'ext/bg/js/translator.js')
| -rw-r--r-- | ext/bg/js/translator.js | 294 | 
1 files changed, 151 insertions, 143 deletions
| diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index fd414847..e534e0cb 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -25,171 +25,199 @@ class Translator {          this.deinflector = new Deinflector();      } -    loadData({loadEnamDict=true}, callback) { +    loadData(callback) {          if (this.loaded) { -            callback(); -            return; +            return Promise.resolve();          } -        Translator.loadData('bg/data/rules.json') -            .then((response) => { -                this.deinflector.setRules(JSON.parse(response)); -                return Translator.loadData('bg/data/tags.json'); -            }) -            .then((response) => { -                this.tagMeta = JSON.parse(response); -                return Translator.loadData('bg/data/edict.json'); -            }) -            .then((response) => { -                this.dictionary.addTermDict('edict', JSON.parse(response)); -                return Translator.loadData('bg/data/kanjidic.json'); -            }) -            .then((response) => { -                this.dictionary.addKanjiDict('kanjidic', JSON.parse(response)); -                return loadEnamDict ? Translator.loadData('bg/data/enamdict.json') : Promise.resolve(null); -            }) -            .then((response) => { -                if (response !== null) { -                    this.dictionary.addTermDict('enamdict', JSON.parse(response)); +        return loadJson('bg/data/rules.json').then(rules => { +            this.deinflector.setRules(rules); +            return loadJson('bg/data/tags.json'); +        }).then(tagMeta => { +            this.tagMeta = tagMeta; +            return this.dictionary.prepareDb(); +        }).then(exists => { +            if (exists) { +                return; +            } + +            if (callback) { +                callback({state: 'begin', progress: 0}); +            } + +            const banks = {}; +            const bankCallback = (loaded, total, indexUrl) => { +                banks[indexUrl] = {loaded, total}; + +                let percent = 0.0; +                for (const url in banks) { +                    percent += banks[url].loaded / banks[url].total;                  } -                this.loaded = true; -                callback(); -            }); -    } +                percent /= 3.0; -    findTerm(text) { -        const groups = {}; -        for (let i = text.length; i > 0; --i) { -            const term = text.slice(0, i); -            const dfs = this.deinflector.deinflect(term, t => { -                const tags = []; -                for (const d of this.dictionary.findTerm(t)) { -                    tags.push(d.tags); +                if (callback) { +                    callback({state: 'update', progress: Math.ceil(100.0 * percent)});                  } +            }; -                return tags; +            return Promise.all([ +                this.dictionary.importTermDict('bg/data/edict/index.json', bankCallback), +                this.dictionary.importTermDict('bg/data/enamdict/index.json', bankCallback), +                this.dictionary.importKanjiDict('bg/data/kanjidic/index.json', bankCallback), +            ]).then(() => { +                return this.dictionary.sealDb(); +            }).then(() => { +                if (callback) { +                    callback({state: 'end', progress: 100.0}); +                }              }); +        }).then(() => { +            this.loaded = true; +        }); +    } -            if (dfs === null) { -                continue; -            } +    findTermGroups(text) { +        const deinflectGroups = {}; +        const deinflectPromises = []; -            for (const df of dfs) { -                this.processTerm(groups, df.source, df.tags, df.rules, df.root); -            } +        for (let i = text.length; i > 0; --i) { +            deinflectPromises.push( +                this.deinflector.deinflect(text.slice(0, i), term => { +                    return this.dictionary.findTerm(term).then(definitions => definitions.map(definition => definition.tags)); +                }).then(deinflects => { +                    const processPromises = []; +                    for (const deinflect of deinflects) { +                        processPromises.push(this.processTerm( +                            deinflectGroups, +                            deinflect.source, +                            deinflect.tags, +                            deinflect.rules, +                            deinflect.root +                        )); +                    } + +                    return Promise.all(processPromises); +                }) +            );          } -        let definitions = []; -        for (const key in groups) { -            definitions.push(groups[key]); -        } +        return Promise.all(deinflectPromises).then(() => deinflectGroups); +    } -        definitions = definitions.sort((v1, v2) => { -            const sl1 = v1.source.length; -            const sl2 = v2.source.length; -            if (sl1 > sl2) { -                return -1; -            } else if (sl1 < sl2) { -                return 1; +    findTerm(text) { +        return this.findTermGroups(text).then(deinflectGroups => { +            let definitions = []; +            for (const key in deinflectGroups) { +                definitions.push(deinflectGroups[key]);              } -            const s1 = v1.score; -            const s2 = v2.score; -            if (s1 > s2) { -                return -1; -            } else if (s1 < s2) { -                return 1; -            } +            definitions = definitions.sort((v1, v2) => { +                const sl1 = v1.source.length; +                const sl2 = v2.source.length; +                if (sl1 > sl2) { +                    return -1; +                } else if (sl1 < sl2) { +                    return 1; +                } -            const rl1 = v1.rules.length; -            const rl2 = v2.rules.length; -            if (rl1 < rl2) { -                return -1; -            } else if (rl1 > rl2) { -                return 1; -            } +                const s1 = v1.score; +                const s2 = v2.score; +                if (s1 > s2) { +                    return -1; +                } else if (s1 < s2) { +                    return 1; +                } -            return v2.expression.localeCompare(v1.expression); -        }); +                const rl1 = v1.rules.length; +                const rl2 = v2.rules.length; +                if (rl1 < rl2) { +                    return -1; +                } else if (rl1 > rl2) { +                    return 1; +                } -        let length = 0; -        for (const result of definitions) { -            length = Math.max(length, result.source.length); -        } +                return v2.expression.localeCompare(v1.expression); +            }); + +            let length = 0; +            for (const result of definitions) { +                length = Math.max(length, result.source.length); +            } -        return {definitions: definitions, length: length}; +            return {definitions, length}; +        });      }      findKanji(text) { -        let definitions = [];          const processed = {}; +        const promises = [];          for (const c of text) {              if (!processed[c]) { -                definitions = definitions.concat(this.dictionary.findKanji(c)); +                promises.push(this.dictionary.findKanji(c).then((definitions) => definitions));                  processed[c] = true;              }          } -        return this.processKanji(definitions); +        return Promise.all(promises).then(sets => this.processKanji(sets.reduce((a, b) => a.concat(b))));      }      processTerm(groups, source, tags, rules, root) { -        for (const entry of this.dictionary.findTerm(root)) { -            if (entry.id in groups) { -                continue; -            } +        return this.dictionary.findTerm(root).then(definitions => { +            for (const definition of definitions) { +                if (definition.id in groups) { +                    continue; +                } -            let matched = tags.length === 0; -            for (const tag of tags) { -                if (entry.tags.indexOf(tag) !== -1) { -                    matched = true; -                    break; +                let matched = tags.length === 0; +                for (const tag of tags) { +                    if (definition.tags.includes(tag)) { +                        matched = true; +                        break; +                    }                  } -            } -            if (!matched) { -                continue; -            } +                if (!matched) { +                    continue; +                } -            const tagItems = []; -            for (const tag of entry.tags) { -                const tagItem = { -                    name: tag, -                    class: 'default', -                    order: Number.MAX_SAFE_INTEGER, -                    score: 0, -                    desc: entry.entities[tag] || '', -                }; +                const tagItems = []; +                for (const tag of definition.tags) { +                    const tagItem = { +                        name: tag, +                        class: 'default', +                        order: Number.MAX_SAFE_INTEGER, +                        score: 0, +                        desc: definition.entities[tag] || '', +                    }; + +                    this.applyTagMeta(tagItem); +                    tagItems.push(tagItem); +                } -                this.applyTagMeta(tagItem); -                tagItems.push(tagItem); -            } +                let score = 0; +                for (const tagItem of tagItems) { +                    score += tagItem.score; +                } -            let score = 0; -            for (const tagItem of tagItems) { -                score += tagItem.score; +                groups[definition.id] = { +                    score, +                    source, +                    rules, +                    expression: definition.expression, +                    reading: definition.reading, +                    glossary: definition.glossary, +                    tags: Translator.sortTags(tagItems) +                };              } - -            groups[entry.id] = { -                score, -                source, -                rules, -                expression: entry.expression, -                reading: entry.reading, -                glossary: entry.glossary, -                tags: Translator.sortTags(tagItems) -            }; -        } +        });      } -    processKanji(entries) { -        const results = []; - -        for (const entry of entries) { +    processKanji(definitions) { +        for (const definition of definitions) {              const tagItems = []; -            for (const tag of entry.tags) { +            for (const tag of definition.tags) {                  const tagItem = {                      name: tag,                      class: 'default', @@ -201,16 +229,10 @@ class Translator {                  tagItems.push(tagItem);              } -            results.push({ -                character: entry.character, -                kunyomi: entry.kunyomi, -                onyomi: entry.onyomi, -                glossary: entry.glossary, -                tags: Translator.sortTags(tagItems) -            }); +            definition.tags = Translator.sortTags(tagItems);          } -        return results; +        return definitions;      }      applyTagMeta(tag) { @@ -241,18 +263,4 @@ class Translator {              return 0;          });      } - -    static isKanji(c) { -        const code = c.charCodeAt(0); -        return code >= 0x4e00 && code < 0x9fb0 || code >= 0x3400 && code < 0x4dc0; -    } - -    static loadData(url) { -        return new Promise((resolve, reject) => { -            const xhr = new XMLHttpRequest(); -            xhr.addEventListener('load', () => resolve(xhr.responseText)); -            xhr.open('GET', chrome.extension.getURL(url), true); -            xhr.send(); -        }); -    }  } |