From a29ac5b9a4ad50b2b840172e574c57463c30e383 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 8 Jan 2022 17:16:48 -0500 Subject: Add English translation for unicode emoji group names --- src/i18n/en.json | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/i18n') diff --git a/src/i18n/en.json b/src/i18n/en.json index 1d494d4a..2a665bd5 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -199,6 +199,17 @@ "add_emoji": "Insert emoji", "custom": "Custom emoji", "unicode": "Unicode emoji", + "unicode_groups": { + "activities": "Activities", + "animals-and-nature": "Animals & Nature", + "flags": "Flags", + "food-and-drink": "Food & Drink", + "objects": "Objects", + "people-and-body": "People & Body", + "smileys-and-emotion": "Smileys & Emotion", + "symbols": "Symbols", + "travel-and-places": "Travel & Places" + }, "load_all_hint": "Loaded first {saneAmount} emoji, loading all emoji may cause performance issues.", "load_all": "Loading all {emojiAmount} emoji" }, -- cgit v1.2.3-70-g09d2 From d5411c9f8809fad02b068f1b59dec59729aafd80 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 20 Sep 2022 19:27:26 -0400 Subject: Extract language list to its own file --- package.json | 5 +++-- src/i18n/languages.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/i18n/messages.js | 45 ++++++++++++--------------------------------- yarn.lock | 5 +++++ 4 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 src/i18n/languages.js (limited to 'src/i18n') diff --git a/package.json b/package.json index 5a2407c6..b0c06a61 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@fortawesome/free-solid-svg-icons": "6.2.0", "@fortawesome/vue-fontawesome": "3.0.1", "@kazvmoe-infra/pinch-zoom-element": "1.2.0", + "@kazvmoe-infra/unicode-emoji-json": "^0.4.0", "@ruffle-rs/ruffle": "0.1.0-nightly.2022.7.12", "@vuelidate/core": "2.0.0-alpha.44", "@vuelidate/validators": "2.0.0-alpha.31", @@ -34,8 +35,8 @@ "escape-html": "1.0.3", "js-cookie": "3.0.1", "localforage": "1.10.0", - "parse-link-header": "2.0.0", "lozad": "^1.16.0", + "parse-link-header": "2.0.0", "phoenix": "1.6.2", "punycode.js": "2.1.0", "qrcode": "1.5.0", @@ -116,8 +117,8 @@ "stylelint": "13.13.1", "stylelint-config-standard": "20.0.0", "stylelint-rscss": "0.4.0", - "vue-loader": "17.0.0", "unicode-emoji-json": "^0.3.0", + "vue-loader": "17.0.0", "vue-style-loader": "4.1.3", "webpack": "5.74.0", "webpack-dev-middleware": "3.7.3", diff --git a/src/i18n/languages.js b/src/i18n/languages.js new file mode 100644 index 00000000..b1cb1d7e --- /dev/null +++ b/src/i18n/languages.js @@ -0,0 +1,44 @@ + +const languages = [ + 'ar', + 'ca', + 'cs', + 'de', + 'eo', + 'en', + 'es', + 'et', + 'eu', + 'fi', + 'fr', + 'ga', + 'he', + 'hu', + 'it', + 'ja', + 'ja_easy', + 'ko', + 'nb', + 'nl', + 'oc', + 'pl', + 'pt', + 'ro', + 'ru', + 'sk', + 'te', + 'uk', + 'zh', + 'zh_Hant' +] + +const specialJsonName = { + ja: 'ja_pedantic' +} + +const langCodeToJsonName = (code) => specialJsonName[code] || code + +module.exports = { + languages, + langCodeToJsonName +} diff --git a/src/i18n/messages.js b/src/i18n/messages.js index eae75c80..8cf25973 100644 --- a/src/i18n/messages.js +++ b/src/i18n/messages.js @@ -7,46 +7,25 @@ // sed -i -e "s/'//gm" -e 's/"/\\"/gm' -re 's/^( +)(.+?): ((.+?))?(,?)(\{?)$/\1"\2": "\4"/gm' -e 's/\"\{\"/{/g' -e 's/,"$/",/g' file.json // There's only problem that apostrophe character ' gets replaced by \\ so you have to fix it manually, sorry. -const loaders = { - ar: () => import('./ar.json'), - ca: () => import('./ca.json'), - cs: () => import('./cs.json'), - de: () => import('./de.json'), - eo: () => import('./eo.json'), - es: () => import('./es.json'), - et: () => import('./et.json'), - eu: () => import('./eu.json'), - fi: () => import('./fi.json'), - fr: () => import('./fr.json'), - ga: () => import('./ga.json'), - he: () => import('./he.json'), - hu: () => import('./hu.json'), - it: () => import('./it.json'), - ja: () => import('./ja_pedantic.json'), - ja_easy: () => import('./ja_easy.json'), - ko: () => import('./ko.json'), - nb: () => import('./nb.json'), - nl: () => import('./nl.json'), - oc: () => import('./oc.json'), - pl: () => import('./pl.json'), - pt: () => import('./pt.json'), - ro: () => import('./ro.json'), - ru: () => import('./ru.json'), - sk: () => import('./sk.json'), - te: () => import('./te.json'), - uk: () => import('./uk.json'), - zh: () => import('./zh.json'), - zh_Hant: () => import('./zh_Hant.json') +import { languages, langCodeToJsonName } from './languages.js' + +const hasLanguageFile = (code) => languages.includes(code) + +const loadLanguageFile = (code) => { + return import( + /* webpackInclude: /\.json$/ */ + `./${langCodeToJsonName(code)}.json` + ) } const messages = { - languages: ['en', ...Object.keys(loaders)], + languages, default: { en: require('./en.json').default }, setLanguage: async (i18n, language) => { - if (loaders[language]) { - const messages = await loaders[language]() + if (hasLanguageFile(language)) { + const messages = await loadLanguageFile(language) i18n.setLocaleMessage(language, messages.default) } i18n.locale = language diff --git a/yarn.lock b/yarn.lock index a971bf9a..f1cfc7f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1629,6 +1629,11 @@ dependencies: pointer-tracker "^2.0.3" +"@kazvmoe-infra/unicode-emoji-json@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@kazvmoe-infra/unicode-emoji-json/-/unicode-emoji-json-0.4.0.tgz#555bab2f8d11db74820ef0a2fbe2805b17c22587" + integrity sha512-22OffREdHzD0U6A/W4RaFPV8NR73za6euibtAxNxO/fu5A6TwxRO2lAdbDWKJH9COv/vYs8zqfEiSalXH2nXJA== + "@nightwatch/chai@5.0.2": version "5.0.2" resolved "https://registry.yarnpkg.com/@nightwatch/chai/-/chai-5.0.2.tgz#86b20908fc090dffd5c9567c0392bc6a494cc2e6" -- cgit v1.2.3-70-g09d2 From 1c3bdda14c0edf4ce321745bcf43e395635d6bf1 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 20 Sep 2022 20:15:32 -0400 Subject: Load unicode emoji annotations --- src/i18n/languages.js | 10 +++++++++- src/modules/config.js | 1 + src/modules/instance.js | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src/i18n') diff --git a/src/i18n/languages.js b/src/i18n/languages.js index b1cb1d7e..40cf04f2 100644 --- a/src/i18n/languages.js +++ b/src/i18n/languages.js @@ -38,7 +38,15 @@ const specialJsonName = { const langCodeToJsonName = (code) => specialJsonName[code] || code +const langCodeToCldrName = (code) => code + +const ensureFinalFallback = codes => { + return codes.includes('en') ? codes : codes.concat(['en']) +} + module.exports = { languages, - langCodeToJsonName + langCodeToJsonName, + langCodeToCldrName, + ensureFinalFallback } diff --git a/src/modules/config.js b/src/modules/config.js index eeaac917..c966602e 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -183,6 +183,7 @@ const config = { break case 'interfaceLanguage': messages.setLanguage(this.getters.i18n, value) + dispatch('loadUnicodeEmojiData', value) Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value)) break case 'thirdColumnMode': diff --git a/src/modules/instance.js b/src/modules/instance.js index 9df01bfd..c0c7cef0 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -2,6 +2,7 @@ import { getPreset, applyTheme } from '../services/style_setter/style_setter.js' import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js' import apiService from '../services/api/api.service.js' import { instanceDefaultProperties } from './config.js' +import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js' const SORTED_EMOJI_GROUP_IDS = [ 'smileys-and-emotion', @@ -78,6 +79,7 @@ const defaultState = { customEmojiFetched: false, emoji: {}, emojiFetched: false, + unicodeEmojiAnnotations: {}, pleromaBackend: true, postFormats: [], restrictedNicknames: [], @@ -109,6 +111,12 @@ const defaultState = { } } +const loadAnnotations = (lang) => { + return import( + `@kazvmoe-infra/unicode-emoji-json/annotations/${langCodeToCldrName(lang)}.json` + ) +} + const instance = { state: defaultState, mutations: { @@ -119,6 +127,9 @@ const instance = { }, setKnownDomains (state, domains) { state.knownDomains = domains + }, + setUnicodeEmojiAnnotations (state, { lang, annotations }) { + state.unicodeEmojiAnnotations[lang] = annotations } }, getters: { @@ -206,6 +217,19 @@ const instance = { } }, + loadUnicodeEmojiData ({ commit, state }, language) { + const langList = ensureFinalFallback(Array.isArray(language) ? language : [language]) + + return Promise.all( + langList + .forEach(async lang => { + if (!state.unicodeEmojiAnnotations[lang]) { + const annotations = await loadAnnotations(lang) + commit('setUnicodeEmojiAnnotations', { lang, annotations }) + } + })) + }, + async getCustomEmoji ({ commit, state }) { try { const res = await window.fetch('/api/pleroma/emoji.json') -- cgit v1.2.3-70-g09d2 From a73f9731f5ad78d1e6f1bd211ad2971d21fc1379 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 20 Sep 2022 20:44:52 -0400 Subject: Display localized unicode emoji names --- src/components/emoji_picker/emoji_picker.js | 20 ++++++++++++++++++++ src/components/emoji_picker/emoji_picker.vue | 2 +- src/i18n/languages.js | 3 ++- src/modules/instance.js | 18 +++++++++++++++--- 4 files changed, 38 insertions(+), 5 deletions(-) (limited to 'src/i18n') diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index c2ae76f3..2ebead53 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -1,6 +1,7 @@ import { defineAsyncComponent } from 'vue' import Checkbox from '../checkbox/checkbox.vue' import StillImage from '../still-image/still-image.vue' +import { ensureFinalFallback } from '../../i18n/languages.js' import lozad from 'lozad' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -285,6 +286,25 @@ const EmojiPicker = { this.waitForDomAndInitializeLazyLoad() this.filteredEmojiGroups = this.getFilteredEmojiGroups() }, 500) + }, + languages () { + console.log('languages:', ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)) + return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage) + }, + maybeLocalizedEmojiName () { + return emoji => { + if (!emoji.annotations) { + return emoji.displayText + } + + for (const lang of this.languages) { + if (emoji.annotations[lang]?.name) { + return emoji.annotations[lang].name + } + } + + return emoji.displayText + } } } } diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index 689138e6..57bb0037 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -88,7 +88,7 @@ diff --git a/src/i18n/languages.js b/src/i18n/languages.js index 40cf04f2..250b3b1a 100644 --- a/src/i18n/languages.js +++ b/src/i18n/languages.js @@ -41,7 +41,8 @@ const langCodeToJsonName = (code) => specialJsonName[code] || code const langCodeToCldrName = (code) => code const ensureFinalFallback = codes => { - return codes.includes('en') ? codes : codes.concat(['en']) + const codeList = Array.isArray(codes) ? codes : [codes] + return codeList.includes('en') ? codeList : codeList.concat(['en']) } module.exports = { diff --git a/src/modules/instance.js b/src/modules/instance.js index c0c7cef0..5a72a6d3 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -117,6 +117,18 @@ const loadAnnotations = (lang) => { ) } +const injectAnnotations = (emoji, annotations) => { + const availableLangs = Object.keys(annotations) + + return { + ...emoji, + annotations: availableLangs.reduce((acc, cur) => { + acc[cur] = annotations[cur][emoji.replacement] + return acc + }, {}) + } +} + const instance = { state: defaultState, mutations: { @@ -164,13 +176,13 @@ const instance = { }, standardEmojiList (state) { return SORTED_EMOJI_GROUP_IDS - .map(groupId => state.emoji[groupId] || []) + .map(groupId => (state.emoji[groupId] || []).map(k => injectAnnotations(k, state.unicodeEmojiAnnotations))) .reduce((a, b) => a.concat(b), []) }, standardEmojiGroupList (state) { return SORTED_EMOJI_GROUP_IDS.map(groupId => ({ id: groupId, - emojis: state.emoji[groupId] || [] + emojis: (state.emoji[groupId] || []).map(k => injectAnnotations(k, state.unicodeEmojiAnnotations)) })) }, instanceDomain (state) { @@ -218,7 +230,7 @@ const instance = { }, loadUnicodeEmojiData ({ commit, state }, language) { - const langList = ensureFinalFallback(Array.isArray(language) ? language : [language]) + const langList = ensureFinalFallback(language) return Promise.all( langList -- cgit v1.2.3-70-g09d2 From cc58b9b93d4346860e244d2093f0d406eb76954c Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 20 Sep 2022 21:50:40 -0400 Subject: Add regional indicators --- src/components/emoji_picker/emoji_picker.js | 15 +++++++++------ src/i18n/en.json | 3 ++- src/modules/instance.js | 29 +++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 9 deletions(-) (limited to 'src/i18n') diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index bf5e0e43..fafc2af1 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -47,8 +47,8 @@ const UNICODE_EMOJI_GROUP_ICON = { flags: 'flag' } -const maybeLocalizedKeywords = (emoji, languages) => { - const res = [emoji.displayText] +const maybeLocalizedKeywords = (emoji, languages, nameLocalizer) => { + const res = [emoji.displayText, nameLocalizer(emoji)] if (emoji.annotations) { languages.forEach(lang => { const keywords = emoji.annotations[lang]?.keywords || [] @@ -59,13 +59,13 @@ const maybeLocalizedKeywords = (emoji, languages) => { return res } -const filterByKeyword = (list, keyword = '', languages) => { +const filterByKeyword = (list, keyword = '', languages, nameLocalizer) => { if (keyword === '') return list const keywordLowercase = keyword.toLowerCase() const orderedEmojiList = [] for (const emoji of list) { - const indices = maybeLocalizedKeywords(emoji, languages) + const indices = maybeLocalizedKeywords(emoji, languages, nameLocalizer) .map(k => k.toLowerCase().indexOf(keywordLowercase)) .filter(k => k > -1) @@ -189,7 +189,7 @@ const EmojiPicker = { this.showingStickers = value }, filterByKeyword (list, keyword) { - return filterByKeyword(list, keyword, this.languages) + return filterByKeyword(list, keyword, this.languages, this.maybeLocalizedEmojiName) }, initializeLazyLoad () { this.destroyLazyLoad() @@ -305,7 +305,6 @@ const EmojiPicker = { }, 500) }, languages () { - console.log('languages:', ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)) return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage) }, maybeLocalizedEmojiName () { @@ -314,6 +313,10 @@ const EmojiPicker = { return emoji.displayText } + if (emoji.displayTextI18n) { + return this.$t(emoji.displayTextI18n.key, emoji.displayTextI18n.args) + } + for (const lang of this.languages) { if (emoji.annotations[lang]?.name) { return emoji.annotations[lang].name diff --git a/src/i18n/en.json b/src/i18n/en.json index 2a665bd5..fb941c8d 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -211,7 +211,8 @@ "travel-and-places": "Travel & Places" }, "load_all_hint": "Loaded first {saneAmount} emoji, loading all emoji may cause performance issues.", - "load_all": "Loading all {emojiAmount} emoji" + "load_all": "Loading all {emojiAmount} emoji", + "regional_indicator": "Regional indicator {letter}" }, "errors": { "storage_unavailable": "Pleroma could not access browser storage. Your login or your local settings won't be saved and you might encounter unexpected issues. Try enabling cookies." diff --git a/src/modules/instance.js b/src/modules/instance.js index 5a72a6d3..9be35d88 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -16,6 +16,26 @@ const SORTED_EMOJI_GROUP_IDS = [ 'flags' ] +const REGIONAL_INDICATORS = (() => { + const start = 0x1F1E6 + const end = 0x1F1FF + const A = 'A'.codePointAt(0) + const res = new Array(end - start + 1) + for (let i = start; i <= end; ++i) { + const letter = String.fromCodePoint(A + i - start) + res[i - start] = { + replacement: String.fromCodePoint(i), + imageUrl: false, + displayText: 'regional_indicator_' + letter, + displayTextI18n: { + key: 'emoji.regional_indicator', + args: { letter } + } + } + } + return res +})() + const defaultState = { // Stuff from apiConfig name: 'Pleroma FE', @@ -129,6 +149,11 @@ const injectAnnotations = (emoji, annotations) => { } } +const injectRegionalIndicators = groups => { + groups.symbols.push(...REGIONAL_INDICATORS) + return groups +} + const instance = { state: defaultState, mutations: { @@ -219,7 +244,7 @@ const instance = { })) return res }, {}) - commit('setInstanceOption', { name: 'emoji', value: emoji }) + commit('setInstanceOption', { name: 'emoji', value: injectRegionalIndicators(emoji) }) } else { throw (res) } @@ -234,7 +259,7 @@ const instance = { return Promise.all( langList - .forEach(async lang => { + .map(async lang => { if (!state.unicodeEmojiAnnotations[lang]) { const annotations = await loadAnnotations(lang) commit('setUnicodeEmojiAnnotations', { lang, annotations }) -- cgit v1.2.3-70-g09d2 From a758e18dceb4cb11d84d6dff1cdfddb755af60db Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 20 Sep 2022 23:13:07 -0400 Subject: Make chunks named --- .babelrc | 2 +- build/webpack.base.conf.js | 3 ++- src/i18n/messages.js | 1 + src/modules/instance.js | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/i18n') diff --git a/.babelrc b/.babelrc index 373d2c59..4ec10416 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,5 @@ { "presets": ["@babel/preset-env"], "plugins": ["@babel/plugin-transform-runtime", "lodash", "@vue/babel-plugin-jsx"], - "comments": false + "comments": true } diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index 78b75e3f..bf946922 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -24,7 +24,8 @@ module.exports = { output: { path: config.build.assetsRoot, publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, - filename: '[name].js' + filename: '[name].js', + chunkFilename: '[name].js' }, optimization: { splitChunks: { diff --git a/src/i18n/messages.js b/src/i18n/messages.js index 8cf25973..74a89ca8 100644 --- a/src/i18n/messages.js +++ b/src/i18n/messages.js @@ -14,6 +14,7 @@ const hasLanguageFile = (code) => languages.includes(code) const loadLanguageFile = (code) => { return import( /* webpackInclude: /\.json$/ */ + /* webpackChunkName: "i18n/[request]" */ `./${langCodeToJsonName(code)}.json` ) } diff --git a/src/modules/instance.js b/src/modules/instance.js index 9f326d26..b1bc9779 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -133,6 +133,7 @@ const defaultState = { const loadAnnotations = (lang) => { return import( + /* webpackChunkName: "emoji-annotations/[request]" */ `@kazvmoe-infra/unicode-emoji-json/annotations/${langCodeToCldrName(lang)}.json` ) .then(k => k.default) @@ -234,7 +235,7 @@ const instance = { }, async getStaticEmoji ({ commit }) { try { - const values = (await import('../../static/emoji.json')).default + const values = (await import(/* webpackChunkName: 'emoji' */ '../../static/emoji.json')).default const emoji = Object.keys(values).reduce((res, groupId) => { res[groupId] = values[groupId].map(e => ({ -- cgit v1.2.3-70-g09d2