Files
rappaurio-sae501_502/app/node_modules/cejs/extension/zh_conversion.js
2023-09-25 13:27:24 +02:00

458 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @name CeL function for 繁簡中文字詞彙轉換。
*
* TODO:<br />
* 在量大的時候,此方法速度頗慢。 Using Map()<br />
* words conversion
*
* @fileoverview 本檔案包含了繁體/簡體中文轉換的 functions。
* @example <code>
// 在非 Windows 平台上避免 fatal 錯誤。
CeL.env.ignore_COM_error = true;
// load module for CeL.CN_to_TW('简体')
CeL.run('extension.zh_conversion', function() {
var text = CeL.CN_to_TW('简体中文文字');
CeL.CN_to_TW.file('from.htm', 'to.htm', 'utf-8');
});
</code>
* @see https://github.com/BYVoid/OpenCC https://zhconvert.org/
* https://en.wiktionary.org/wiki/Module:zh
* @since 2014/6/17 22:39:16
*/
'use strict';
// --------------------------------------------------------------------------------------------
// 不採用 if 陳述式,可以避免 Eclipse JSDoc 與 format 多縮排一層。
typeof CeL === 'function' && CeL.run({
// module name
name : 'extension.zh_conversion',
require : 'data.|data.Convert_Pairs.|application.OS.Windows.file.',
// 設定不匯出的子函式。
no_extend : 'generate_converter',
// 為了方便格式化程式碼,因此將 module 函式主體另外抽出。
code : module_code
});
function module_code(library_namespace) {
// requiring
var Convert_Pairs = library_namespace.data.Convert_Pairs;
/**
* null module constructor
*
* @class 中文繁簡轉換的 functions
*/
var _// JSDT:_module_
= function() {
// null module constructor
};
/**
* for JSDT: 有 prototype 才會將之當作 Class
*/
_// JSDT:_module_
.prototype = {};
// ------------------------------------------------------------------------
// new RegExp(key, REPLACE_FLAG);
var REPLACE_FLAG = undefined,
// using BYVoid / OpenCC 開放中文轉換 (Open Chinese Convert) table.
// https://github.com/BYVoid/OpenCC/tree/master/data/dictionary
dictionary_base = library_namespace.get_module_path(this.id, 'OpenCC'
+ library_namespace.env.path_separator);
// console.log('dictionary_base: ' + dictionary_base);
function Converter(options) {
// console.log(options);
// e.g., .files, .file_filter
Object.assign(this, options);
// console.trace(this.files);
}
function Converter_initialization(options) {
// console.trace(this.files);
function item_processor(item) {
var matched = item.match(/^([^\t]+)\t([^\t]+)$/);
if (matched) {
if (!matched[1].trim())
return;
if (/ [^\t]+$/.test(matched[2])) {
if (matched[2].startsWith(matched[1] + ' ')) {
// console.log('詞有疑意: ' + item);
// 但像是"小丑"之類的還是必須保留。
// return;
}
// 必須置換,那就換個最常用的。
return item.replace(/ +[^\t]+$/, '');
}
}
return item;
}
function corrections_item_processor(item, options) {
var matched = item.match(/^-([^\t\n]{1,30})$/);
if (!matched) {
return item;
}
remove_key_hash[matched[1]] = options.path;
return '';
}
function to_full_file_path(file_path) {
return /[\\\/]/.test(file_path) ? file_path : dictionary_base
+ file_path + '.txt';
}
this.conversions = [];
this.files.map(function(file_list) {
var _options = {
file_filter : this.file_filter,
// no_the_same_key_value : !Array.isArray(file_list)
// || file_list.length < 2,
item_processor : item_processor,
// 在開始轉換之後就不會再修改辭典檔,因此可移除 .pair_Map。
may_remove_pair_Map : !options || !options.mode
};
if (!Array.isArray(file_list))
file_list = [ file_list ];
_options.path = file_list
// 載入 resources。
.map(function(file_path) {
if (typeof file_path === 'string')
return to_full_file_path(file_path);
// assert: library_namespace.is_Object(file_path)
var __options = file_path;
// e.g., for .remove_comments
if (!__options.file_path && !__options.path
//
&& __options.file_name) {
__options.file_path
//
= to_full_file_path(__options.file_name);
}
// assert: !!__options.file_path === true
return __options;
});
var convert_Pairs = new Convert_Pairs(null, _options);
if (convert_Pairs.pair_Map.size > 0) {
// console.trace([ convert_Pairs.pair_Map.get('猜拳斗酒') ]);
this.conversions.push(convert_Pairs);
}
}, this);
delete this.file_filter;
// console.log(this.conversions);
// console.trace(this.conversions[0].pair_Map.size);
// --------------------------------------
if (this.corrections) {
// keys_to_remove
var remove_key_hash = Object.create(null);
// this.conversions: 手動修正表。提供自行更改的功能。
this.conversions.push(new Convert_Pairs(null, {
path : dictionary_base.replace(/[^\\\/]+[\\\/]$/,
this.corrections),
item_processor : corrections_item_processor,
remove_comments : true
}));
delete this.corrections;
if (!library_namespace.is_empty_object(remove_key_hash)) {
this.conversions.forEach(function(conversion) {
// console.trace(conversion.pair_Map.get('猜拳斗酒'));
if (false && conversion.pair_Map.get('猜拳斗酒')) {
console.log(conversion);
throw conversion.pair_Map.get('猜拳斗酒');
}
conversion.remove(remove_key_hash, {
remove_matched_path : true
});
});
// free
remove_key_hash = null;
}
}
// 設定事前轉換表。
if (this.prefix_conversions) {
this.conversions.unshift(new Convert_Pairs(this.prefix_conversions,
{
flags : this.flags || REPLACE_FLAG
}));
delete this.prefix_conversions;
}
// 設定事後轉換表。
if (this.postfix_conversions) {
this.conversions.push(new Convert_Pairs(this.postfix_conversions, {
flags : this.flags || REPLACE_FLAG
}));
delete this.postfix_conversions;
}
// console.trace(this('签'));
}
// convert text
function convert_text(text, options) {
if (!this.conversions) {
this.initialization(options);
}
// 事前轉換表。
if (options && options.prefix_conversions) {
text = (new Convert_Pairs(options.prefix_conversions, {
flags : options.flags || REPLACE_FLAG
})).convert(text);
}
var for_each_conversion;
if (!options) {
} else if (options.mode === 'word') {
// 僅轉換完全相符的詞彙 key。
for_each_conversion = function(_text, conversion) {
// console.log(conversion.pair)
var convert_to = conversion.get_value(_text);
return typeof convert_to === 'string' ? convert_to : _text;
};
} else if (false && options.mode === 'word_first') {
// 輸入單一詞彙時使用,以期加快速度...可惜沒有。
// node.js: 直接開 `conversion.convert(text)` 速度相同,且還包含
// .special_keys_Map 的轉換,較完整。
for_each_conversion = function(_text, conversion) {
var convert_to = conversion.get_value(_text);
return typeof convert_to === 'string' ? convert_to : conversion
.convert(_text, options);
};
}
text = this.conversions.reduce(for_each_conversion
|| function(_text, conversion) {
return conversion.convert(_text, options);
}, text);
// console.trace(text);
if (!(this.max_convert_word_length >= 0)) {
this.max_convert_word_length = this.conversions.reduce(function(
length, conversion) {
return Math.max(length, conversion.pair_Map_by_length.length);
}, 0);
// console.trace(this);
if (this['interface'])
this['interface'].max_convert_word_length = this.max_convert_word_length;
}
// 事後轉換表。
if (options && options.postfix_conversions) {
text = (new Convert_Pairs(options.postfix_conversions, {
flags : options.flags || REPLACE_FLAG
})).convert(text);
}
return text;
}
// convert text file
function convert_file(from, to, target_encoding) {
var text = library_namespace.get_file(from);
text = this(text);
library_namespace.write_file(to, text, target_encoding);
}
Object.assign(Converter.prototype, {
initialization : Converter_initialization,
convert : convert_text,
file : convert_file
});
Converter.options = {
CN_to_TW : {
// 事前事後轉換表須事先設定。
// 不可以 Object.assign(CeL.CN_to_TW.prefix_conversions = {}, {})
// 來新增事前轉換表。
// prefix_conversions : {},
// postfix_conversions : {},
files : [ [ 'STPhrases', 'STCharacters',
// 以 generate_additional_table.js 合併新同文堂和 ConvertZZ 的辭典檔。
'additional.to_TW.auto-generated',
// 後來的會覆蓋前面的。
{
file_name : 'additional.to_TW',
remove_comments : true
} ],
// ------------------------------------------------------
// ** 下面的是上面詞彙與單字轉換後的再轉換。
[ 'TWPhrasesIT',
// ↑ TWPhrasesIT.txt 有許多常用詞彙,在 corrections_to_TW.txt 取消。
'TWPhrasesName', 'TWPhrasesOther',
// 若要篩選或增減 conversion files可參考範例
// start_downloading() @ CeL.application.net.work_crawler.task
{
file_name : 'additional.to_TW.phrases',
remove_comments : true
} ],
// https://github.com/BYVoid/OpenCC/blob/master/data/config/s2twp.json
'TWVariants' ],
corrections : 'corrections_to_TW.txt'
},
TW_to_CN : {
// 事前事後轉換表須事先設定。
// prefix_conversions : {},
// postfix_conversions : {},
// https://github.com/BYVoid/OpenCC/blob/master/data/config/tw2s.json
// https://github.com/BYVoid/OpenCC/blob/master/node/dicts.gypi
files : [ 'TWVariantsRevPhrases', [ 'TSPhrases', 'TSCharacters',
// 以 generate_additional_table.js 合併新同文堂和 ConvertZZ 的辭典檔。
'additional.to_CN.auto-generated',
// 後來的會覆蓋前面的。
{
file_name : 'additional.to_CN',
remove_comments : true
} ] ],
// ------------------------------------------------------
// ** 下面的是上面詞彙與單字轉換後的再轉換。
corrections : 'corrections_to_CN.txt'
}
};
// ------------------------------------------------------------------------
function set_as_default(method_name, method) {
library_namespace[method_name] = _[method_name] = method;
}
function generate_converter(type, options) {
options = library_namespace.setup_options(options);
if (!(type in Converter.options)) {
library_namespace.error(
//
'generate_converter: Invalid type: ' + type);
return;
}
var converter = new Converter(Object.assign(Object
.clone(Converter.options[type]), options));
var converter_interface = converter.convert.bind(converter);
converter['interface'] = converter_interface;
if (options.set_as_default) {
set_as_default(type, converter_interface);
}
return converter_interface;
}
var cecc;
function using_CeCC(options) {
// 前置處理。
options = library_namespace.setup_options(options);
if (cecc && !options.force_using_cecc) {
library_namespace.debug('CeCC loaded.');
return true;
}
var CeCC;
try {
CeCC = require('cecc');
} catch (e) {
try {
// base_path/CeJS/ce.js
// base_path/Chinese_converter/Chinese_converter.js
CeCC = require(library_namespace.simplify_path(
//
library_namespace.get_module_path().replace(/[^\\\/]*$/,
'../Chinese_converter/Chinese_converter.js')));
} catch (e) {
}
}
if (!CeCC) {
return;
}
if (!options.try_LTP_server) {
cecc = new CeCC(options);
return setup_CeCC_methods(options);
}
return CeCC.has_LTP_server(options).then(function(LTP_URL) {
if (!LTP_URL)
return;
options.LTP_URL = LTP_URL;
cecc = new CeCC(options);
cecc.is_asynchronous = true;
return setup_CeCC_methods(options);
});
}
function setup_CeCC_methods(options) {
library_namespace.info('using_CeCC: Using CeCC ('
+ (cecc.is_asynchronous ? 'asynchronous' : 'synchronous')
+ ' version) to convert language.');
var methods = {
CN_to_TW : 'to_TW',
TW_to_CN : 'to_TW'
};
for ( var method_name in methods) {
var cecc_name = methods[method_name];
if (!cecc.is_asynchronous)
cecc_name += '_sync';
var method = cecc[cecc_name].bind(cecc);
method.is_CeCC = true;
method.cecc = cecc;
if (cecc.is_asynchronous)
method.is_asynchronous = true;
set_as_default(method_name, method);
}
return true;
}
// ------------------------------------------------------------------------
// export
_.generate_converter = generate_converter;
_.using_CeCC = using_CeCC;
try {
var OpenCC = require('opencc');
// Load the default Simplified to Traditional config
_.CN_to_TW = new OpenCC('s2t.json');
// Sync API
_.CN_to_TW = _.CN_to_TW.convertSync.bind(_.CN_to_TW);
_.TW_to_CN = new OpenCC('t2s.json');
_.TW_to_CN = _.TW_to_CN.convertSync.bind(_.TW_to_CN);
} catch (e) {
// CeL.application.net.work_crawler.task will re-generate the functions!
generate_converter('CN_to_TW', {
set_as_default : true
});
generate_converter('TW_to_CN', {
set_as_default : true
});
}
// Warning: require('cecc') will overwrite CeL.CN_to_TW, CeL.TW_to_CN !
return (_// JSDT:_module_
);
}