diff --git a/.eslintrc.js b/.eslintrc.js index 7ff1ba478..c57821490 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -70,7 +70,9 @@ module.exports = { 'consistent-return': 'error', 'dot-notation': 'error', eqeqeq: 'error', - indent: ['error', 2], + indent: ['error', 2, { + ignoredNodes: ['TemplateLiteral'], + }], 'jsx-quotes': ['error', 'prefer-single'], 'key-spacing': [ 'error', diff --git a/.gitignore b/.gitignore index 29918f5d8..576659c3f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,10 @@ yarn-error.log* .idea .DS_Store +# Custom build files +/custom/* +!/custom/.gitkeep + # surge.sh CNAME AUTH diff --git a/app/soapbox/locales/messages.js b/app/soapbox/locales/messages.js index feaf780a7..bcea22f3c 100644 --- a/app/soapbox/locales/messages.js +++ b/app/soapbox/locales/messages.js @@ -1,65 +1,98 @@ -export default { - 'ar': () => import(/* webpackChunkName: "locale_ar" */'./ar.json'), - 'ast': () => import(/* webpackChunkName: "locale_ast" */'./ast.json'), - 'bg': () => import(/* webpackChunkName: "locale_bg" */'./bg.json'), - 'bn': () => import(/* webpackChunkName: "locale_bn" */'./bn.json'), - 'br': () => import(/* webpackChunkName: "locale_br" */'./br.json'), - 'ca': () => import(/* webpackChunkName: "locale_ca" */'./ca.json'), - 'co': () => import(/* webpackChunkName: "locale_co" */'./co.json'), - 'cs': () => import(/* webpackChunkName: "locale_cs" */'./cs.json'), - 'cy': () => import(/* webpackChunkName: "locale_cy" */'./cy.json'), - 'da': () => import(/* webpackChunkName: "locale_da" */'./da.json'), - 'de': () => import(/* webpackChunkName: "locale_de" */'./de.json'), - 'el': () => import(/* webpackChunkName: "locale_el" */'./el.json'), - 'en': () => import(/* webpackChunkName: "locale_en" */'./en.json'), - 'en-Shaw': () => import(/* webpackChunkName: "locale_en-Shaw" */'./en-Shaw.json'), - 'eo': () => import(/* webpackChunkName: "locale_eo" */'./eo.json'), - 'es-AR': () => import(/* webpackChunkName: "locale_es-AR" */'./es-AR.json'), - 'es': () => import(/* webpackChunkName: "locale_es" */'./es.json'), - 'et': () => import(/* webpackChunkName: "locale_et" */'./et.json'), - 'eu': () => import(/* webpackChunkName: "locale_eu" */'./eu.json'), - 'fa': () => import(/* webpackChunkName: "locale_fa" */'./fa.json'), - 'fi': () => import(/* webpackChunkName: "locale_fi" */'./fi.json'), - 'fr': () => import(/* webpackChunkName: "locale_fr" */'./fr.json'), - 'ga': () => import(/* webpackChunkName: "locale_ga" */'./ga.json'), - 'gl': () => import(/* webpackChunkName: "locale_gl" */'./gl.json'), - 'he': () => import(/* webpackChunkName: "locale_he" */'./he.json'), - 'hi': () => import(/* webpackChunkName: "locale_hi" */'./hi.json'), - 'hr': () => import(/* webpackChunkName: "locale_hr" */'./hr.json'), - 'hu': () => import(/* webpackChunkName: "locale_hu" */'./hu.json'), - 'hy': () => import(/* webpackChunkName: "locale_hy" */'./hy.json'), - 'id': () => import(/* webpackChunkName: "locale_id" */'./id.json'), - 'io': () => import(/* webpackChunkName: "locale_io" */'./io.json'), - 'it': () => import(/* webpackChunkName: "locale_it" */'./it.json'), - 'ja': () => import(/* webpackChunkName: "locale_ja" */'./ja.json'), - 'ka': () => import(/* webpackChunkName: "locale_ka" */'./ka.json'), - 'kk': () => import(/* webpackChunkName: "locale_kk" */'./kk.json'), - 'ko': () => import(/* webpackChunkName: "locale_ko" */'./ko.json'), - 'lt': () => import(/* webpackChunkName: "locale_lt" */'./lt.json'), - 'lv': () => import(/* webpackChunkName: "locale_lv" */'./lv.json'), - 'mk': () => import(/* webpackChunkName: "locale_mk" */'./mk.json'), - 'ms': () => import(/* webpackChunkName: "locale_ms" */'./ms.json'), - 'nl': () => import(/* webpackChunkName: "locale_nl" */'./nl.json'), - 'nn': () => import(/* webpackChunkName: "locale_nn" */'./nn.json'), - 'no': () => import(/* webpackChunkName: "locale_no" */'./no.json'), - 'oc': () => import(/* webpackChunkName: "locale_oc" */'./oc.json'), - 'pl': () => import(/* webpackChunkName: "locale_pl" */'./pl.json'), - 'pt-BR': () => import(/* webpackChunkName: "locale_pt-BR" */'./pt-BR.json'), - 'pt': () => import(/* webpackChunkName: "locale_pt" */'./pt.json'), - 'ro': () => import(/* webpackChunkName: "locale_ro" */'./ro.json'), - 'ru': () => import(/* webpackChunkName: "locale_ru" */'./ru.json'), - 'sk': () => import(/* webpackChunkName: "locale_sk" */'./sk.json'), - 'sl': () => import(/* webpackChunkName: "locale_sl" */'./sl.json'), - 'sq': () => import(/* webpackChunkName: "locale_sq" */'./sq.json'), - 'sr': () => import(/* webpackChunkName: "locale_sr" */'./sr.json'), - 'sr-Latn': () => import(/* webpackChunkName: "locale_sr-Latn" */'./sr-Latn.json'), - 'sv': () => import(/* webpackChunkName: "locale_sv" */'./sv.json'), - 'ta': () => import(/* webpackChunkName: "locale_ta" */'./ta.json'), - 'te': () => import(/* webpackChunkName: "locale_te" */'./te.json'), - 'th': () => import(/* webpackChunkName: "locale_th" */'./th.json'), - 'tr': () => import(/* webpackChunkName: "locale_tr" */'./tr.json'), - 'uk': () => import(/* webpackChunkName: "locale_uk" */'./uk.json'), - 'zh-CN': () => import(/* webpackChunkName: "locale_zh-CN" */'./zh-CN.json'), - 'zh-HK': () => import(/* webpackChunkName: "locale_zh-HK" */'./zh-HK.json'), - 'zh-TW': () => import(/* webpackChunkName: "locale_zh-TW" */'./zh-TW.json'), +// Import custom messages +const importCustom = locale => { + try { + return import(/* webpackChunkName: "locale_[request]" */`custom/locales/${locale}.json`); + } catch(e) { + return new Promise(resolve => resolve({ default: {} })); + } }; + +// Import git-checked messages +const importMessages = locale => { + return import(/* webpackChunkName: "locale_[request]" */`./${locale}.json`); +}; + +// Override custom messages +const importMessagesWithCustom = locale => { + return Promise.all([ + importMessages(locale), + importCustom(locale), + ]).then(messages => { + const [native, custom] = messages; + return Object.assign(native.default, custom.default); + }); +}; + +const locales = [ + 'ar', + 'ast', + 'bg', + 'bn', + 'br', + 'ca', + 'co', + 'cs', + 'cy', + 'da', + 'de', + 'el', + 'en', + 'en-Shaw', + 'eo', + 'es-AR', + 'es', + 'et', + 'eu', + 'fa', + 'fi', + 'fr', + 'ga', + 'gl', + 'he', + 'hi', + 'hr', + 'hu', + 'hy', + 'id', + 'io', + 'it', + 'ja', + 'ka', + 'kk', + 'ko', + 'lt', + 'lv', + 'mk', + 'ms', + 'nl', + 'nn', + 'no', + 'oc', + 'pl', + 'pt-BR', + 'pt', + 'ro', + 'ru', + 'sk', + 'sl', + 'sq', + 'sr', + 'sr-Latn', + 'sv', + 'ta', + 'te', + 'th', + 'tr', + 'uk', + 'zh-CN', + 'zh-HK', + 'zh-TW', +]; + +// Build the export +const messages = locales.reduce((acc, locale) => { + acc[locale] = () => importMessagesWithCustom(locale); + return acc; +}, {}); + +export default messages; diff --git a/custom/.gitkeep b/custom/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/webpack/shared.js b/webpack/shared.js index d77475ba7..648f07008 100644 --- a/webpack/shared.js +++ b/webpack/shared.js @@ -115,6 +115,7 @@ module.exports = { // https://stackoverflow.com/a/35990101/8811886 '@tabler': resolve('node_modules', '@tabler'), 'icons': resolve('app', 'icons'), + 'custom': resolve('custom'), }, fallback: { path: require.resolve('path-browserify'),