UNPKG

hangul-postposition

Version:

Translate proper Hangul postpositions for the Korean language.

152 lines (136 loc) 4.42 kB
/** * @link https://github.com/peecky/hangul-postposition * @license http://opensource.org/licenses/MIT * * @version 2.0.0 */ // encoding:utf8 (function() { "use strict"; var keywords1Half = { '을(를)': ['을', '를'], '이(가)': ['이', '가'], '은(는)': ['은', '는'], '과(와)': ['과', '와'], '아(야)': ['아', '야'], '이어(여)': ['이어', '여'], '이에(예)': ['이에', '예'], '이었(였)': ['이었', '였'], '(이)': ['이', ''] }; var keywords1Full = { '을(를)': ['을', '를'], '를(을)': ['을', '를'], '이(가)': ['이', '가'], // '가(이)': ['이', '가'], '은(는)': ['은', '는'], '는(은)': ['은', '는'], '과(와)': ['과', '와'], '와(과)': ['과', '와'], '아(야)': ['아', '야'], '야(아)': ['아', '야'], '이어(여)': ['이어', '여'], '여(이어)': ['이어', '여'], '이에(예)': ['이에', '예'], '예(이에)': ['이에', '예'], '이었(였)': ['이었', '였'], '였(이었)': ['이었', '였'], '(이)': ['이', ''] }; var keywords2 = { '(으)로': ['으로', '로'] }; function isHangul(chr) { var code = chr.charCodeAt(0); return code >= 0xAC00 && code <= 0xD7A3; } function isTranslatable(chr) { var code = chr.charCodeAt(0); return (code >= 0xAC00 && code <= 0xD7A3) || (code >= 48 && code <= 57); } function hasFinalConsonant(chr) { var code = chr.charCodeAt(0); return (isHangul(chr) && ((code - 0xAC00) % 28 !== 0)) || code === 48 || code === 49 || code === 51 || code === 54 || code === 55 || code === 56; } function hasFinalConsonantRieul(chr) { var code = chr.charCodeAt(0); return (isHangul(chr) && ((code - 0xAC00) % 28 === 8)) || code === 49 || code === 55 || code === 56; } function Hanp() { this._keywords1 = keywords1Half; this._forceTranslate = false; } Hanp.prototype._translate = function(msg, keywords, checkFunction) { var translatedMsg = msg; var keywordsKeys = Object.keys(keywords); for (var i = 0; i < keywordsKeys.length; i++) { var keyword = keywordsKeys[i]; var msgParts = translatedMsg.split(keyword); if (msgParts.length < 2) continue; translatedMsg = ''; for (var j = 0, l = msgParts.length-1; j < l; j++) { translatedMsg += msgParts[j]; var lastChr = msgParts[j].charAt(msgParts[j].length-1); var postposition; if (isTranslatable(lastChr)) postposition = checkFunction(lastChr) ? keywords[keyword][0] : keywords[keyword][1]; else postposition = this._forceTranslate ? keywords[keyword][0] : keyword; translatedMsg += postposition; } translatedMsg += msgParts[j]; } return translatedMsg; }; Hanp.prototype.translatePostpositions = function(msg, properties) { if (properties && properties.locale && properties.locale !== 'ko') return msg; msg = this._translate(msg, this._keywords1, hasFinalConsonant); msg = this._translate(msg, keywords2, function(chr) { return hasFinalConsonant(chr) && !hasFinalConsonantRieul(chr); }); return msg; }; Hanp.prototype.options = function(options) { if (options) { if (typeof options.halfTranslate !== 'undefined') { this._keywords1 = options.halfTranslate ? keywords1Half : keywords1Full; } if (typeof options.forceTranslate !== 'undefined') this._forceTranslate = options.forceTranslate; } }; Hanp.prototype.expressBind = function(app) { var self = this; app.use(function(req, res, next) { // override __() and __n() which come from i18n or i18n-2 if (res.locals) { if (typeof res.locals.__ === 'function') { res.locals._old__ = res.locals.__; res.locals.__ = function() { return self.translatePostpositions(res.locals._old__.apply(this, arguments)); }; } if (typeof res.locals.__n === 'function') { res.locals._old__n = res.locals.__n; res.locals.__n = function() { return self.translatePostpositions(res.locals._old__n.apply(this, arguments)); }; } } next(); }); }; var hanp = new Hanp(); Hanp.translatePostpositions = hanp.translatePostpositions.bind(hanp); Hanp.options = hanp.options.bind(hanp); Hanp.expressBind = hanp.expressBind.bind(hanp); if (typeof window === 'object') { // web browser window.Hanp = Hanp; window.hanp = hanp; } else if (typeof module === 'object' && typeof module.exports === 'object') { // node.js module.exports = Hanp; } })();