diff --git a/lib/i18n.js b/lib/i18n.js new file mode 100644 index 00000000..bf1e1cb0 --- /dev/null +++ b/lib/i18n.js @@ -0,0 +1,109 @@ +const _ = require('lodash'); +const util = require('hexo-util'); +const RFC5646_TAGS = require('./rfc5646'); + +const Pattern = util.Pattern; + +module.exports = function (hexo) { + function pathJoin(...paths) { + return paths.join('/'); + } + + function formatRfc5646(language) { + if (!language) { + return ''; + } + return language.split(/[-_]/).map((l, i) => i === 0 ? l.toLowerCase() : l.toUpperCase()).join('-'); + } + + function formatIso639(language) { + if (!language) { + return ''; + } + return language.split(/[-_]/)[0].toLowerCase(); + } + + function getClosestRfc5646WithCountryCode(language) { + if (!language) { + return ''; + } + const iso639 = formatRfc5646(language).split('-')[0]; + const result = Object.keys(RFC5646_TAGS).find(tag => tag.startsWith(iso639 + '-')); + return result ? result : iso639; + } + + function getUsedLanguages() { + return hexo.theme.i18n.list(); + } + + function getDisplayLanguages() { + let languages = hexo.config.language; + if (!languages) { + return ['default']; + } + languages = [].concat(hexo.config.language); + if (!Array.isArray(languages)) { + languages = [languages]; + } + if (languages.indexOf('default') > -1) { + languages.splice(languages.indexOf('default'), 1); + } + return languages; + } + + function isLanguageValid(language) { + const variants = [language, formatRfc5646(language)]; + return variants.some(variant => RFC5646_TAGS.hasOwnProperty(variant)); + } + + function injectLanguages(func) { + return function(locals) { + return func.call(this, getDisplayLanguages(), locals); + } + } + + function getPageLanguage(post) { + const languages = getUsedLanguages(); + let lang = post.lang || post.language; + if (!lang && post.source) { + const path = post.source.startsWith('_posts/') ? post.source.slice('_posts/'.length) : post.source; + const pattern = new Pattern(`${hexo.config.i18n_dir}/*path`); + const data = pattern.match(path); + + if (data && data.lang && ~languages.indexOf(data.lang)) { + lang = data.lang; + } + } + return lang; + } + + function isDefaultLanguage(language) { + return !language || getDisplayLanguages().indexOf(language) === 0; + } + + function postFilter(language) { + return function (post) { + let lang = getPageLanguage(post); + return lang === language || (isDefaultLanguage(language) && !lang); + } + } + + function url_for(path) { + return hexo.extend.helper.get('url_for').call(hexo, path); + } + + return { + pathJoin, + isDefaultLanguage, + url_for, + postFilter, + injectLanguages, + getUsedLanguages, + getDisplayLanguages, + getPageLanguage, + isLanguageValid, + formatRfc5646, + formatIso639, + getClosestRfc5646WithCountryCode + }; +}; \ No newline at end of file diff --git a/scripts/rfc5646.js b/lib/rfc5646.js similarity index 100% rename from scripts/rfc5646.js rename to lib/rfc5646.js diff --git a/scripts/01_check.js b/scripts/01_check.js index 605b1c32..28f4c170 100644 --- a/scripts/01_check.js +++ b/scripts/01_check.js @@ -50,7 +50,7 @@ if (!fs.existsSync(mainConfigPath)) { logger.warn(`${mainConfigPath} is not found. Please create one from the template _config.yml.example.`) } -const { getUsedLanguages, getDisplayLanguages, isLanguageValid } = require('./10_i18n'); +const { getUsedLanguages, getDisplayLanguages, isLanguageValid } = require('../lib/i18n')(hexo); logger.info('Checking language names against RFC5646 specs'); const invalidLanguages = getUsedLanguages().filter(language => !isLanguageValid(language)); diff --git a/scripts/10_i18n.js b/scripts/10_i18n.js index 940bc358..5242e724 100644 --- a/scripts/10_i18n.js +++ b/scripts/10_i18n.js @@ -5,97 +5,20 @@ const indexGenerator = require('hexo-generator-index/lib/generator'); const archiveGenerator = require('hexo-generator-archive/lib/generator'); const categoryGenerator = require('hexo-generator-category/lib/generator'); const tagGenerator = require('hexo-generator-tag/lib/generator'); - -const RFC5646_TAGS = require('./rfc5646'); - -const Pattern = util.Pattern; - -function pathJoin(...paths) { - return paths.join('/'); -} - -function formatRfc5646(language) { - if (!language) { - return ''; - } - return language.split(/[-_]/).map((l, i) => i === 0 ? l.toLowerCase() : l.toUpperCase()).join('-'); -} - -function formatIso639(language) { - if (!language) { - return ''; - } - return language.split(/[-_]/)[0].toLowerCase(); -} - -function getClosestRfc5646WithCountryCode(language) { - if (!language) { - return ''; - } - const iso639 = formatRfc5646(language).split('-')[0]; - const result = Object.keys(RFC5646_TAGS).find(tag => tag.startsWith(iso639 + '-')); - return result ? result : iso639; -} - -function getUsedLanguages() { - return hexo.theme.i18n.list(); -} - -function getDisplayLanguages() { - let languages = hexo.config.language; - if (!languages) { - return ['default']; - } - languages = [].concat(hexo.config.language); - if (!Array.isArray(languages)) { - languages = [languages]; - } - if (languages.indexOf('default') > -1) { - languages.splice(languages.indexOf('default'), 1); - } - return languages; -} - -function isLanguageValid(language) { - const variants = [language, formatRfc5646(language)]; - return variants.some(variant => RFC5646_TAGS.hasOwnProperty(variant)); -} - -function injectLanguages(func) { - return function(locals) { - return func.call(this, getDisplayLanguages(), locals); - } -} - -function getPageLanguage(post) { - const languages = getUsedLanguages(); - let lang = post.lang || post.language; - if (!lang && post.source) { - const path = post.source.startsWith('_posts/') ? post.source.slice('_posts/'.length) : post.source; - const pattern = new Pattern(`${hexo.config.i18n_dir}/*path`); - const data = pattern.match(path); - - if (data && data.lang && ~languages.indexOf(data.lang)) { - lang = data.lang; - } - } - return lang; -} - -function isDefaultLanguage(language) { - return !language || getDisplayLanguages().indexOf(language) === 0; -} - -function postFilter(language) { - return function (post) { - let lang = getPageLanguage(post); - return lang === language || (isDefaultLanguage(language) && !lang); - } -} - -function url_for(path) { - return hexo.extend.helper.get('url_for').call(hexo, path); -} +const { + pathJoin, + isDefaultLanguage, + url_for, + postFilter, + injectLanguages, + getUsedLanguages, + getDisplayLanguages, + getPageLanguage, + isLanguageValid, + formatRfc5646, + formatIso639, + getClosestRfc5646WithCountryCode +} = require('../lib/i18n')(hexo); /** * Modify previous and next post link @@ -443,14 +366,4 @@ hexo.extend.helper.register('closest_rfc5646_with_country_code', function (langu hexo.extend.helper.register('language_name', function (language) { const name = hexo.theme.i18n.__(language)('name'); return name === 'name' ? language : name; -}); - -module.exports = { - getUsedLanguages, - getDisplayLanguages, - getPageLanguage, - isLanguageValid, - formatRfc5646, - formatIso639, - getClosestRfc5646WithCountryCode -}; \ No newline at end of file +}); \ No newline at end of file diff --git a/scripts/99_content.js b/scripts/99_content.js index 655f18a8..09ec1bc1 100644 --- a/scripts/99_content.js +++ b/scripts/99_content.js @@ -1,7 +1,7 @@ const _ = require('lodash'); const moment = require('moment'); const cheerio = require('cheerio'); -const { formatRfc5646, formatIso639, getClosestRfc5646WithCountryCode, getPageLanguage } = require('./10_i18n'); +const { formatRfc5646, formatIso639, getClosestRfc5646WithCountryCode, getPageLanguage } = require('../lib/i18n')(hexo); const MOMENTJS_SUPPORTED_LANGUAGES = ['af', 'ar-dz', 'ar-kw', 'ar-ly', 'ar-ma', 'ar-sa', 'ar-tn', 'ar', 'az', 'be', 'bg', 'bm', 'bn', 'bo', 'br', 'bs', 'ca', 'cs', 'cv', 'cy',