From 9d81d068533aaddf8e8654f9e86374c6531766bb Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Dec 2020 10:01:32 +0900 Subject: wip --- src/client/.eslintrc | 2 + src/client/@types/global.d.ts | 4 +- src/client/components/abuse-report-window.vue | 4 +- src/client/components/channel-preview.vue | 8 +-- src/client/components/global/i18n.ts | 15 ++++++ src/client/components/index.ts | 2 + src/client/components/note.vue | 8 +-- src/client/components/signup.vue | 4 +- src/client/config.ts | 6 +-- src/client/i18n.ts | 73 ++++++++++++++++----------- src/client/init.ts | 9 ++-- src/client/pages/channel.vue | 4 +- src/client/pages/reversi/game.setting.vue | 8 +-- src/client/pages/reversi/index.vue | 4 +- src/client/pages/settings/2fa.vue | 4 +- src/client/pages/settings/general.vue | 4 +- src/client/pages/timeline.tutorial.vue | 8 +-- src/client/scripts/set-i18n-contexts.ts | 15 ------ src/client/ui/deck.vue | 2 +- 19 files changed, 102 insertions(+), 82 deletions(-) create mode 100644 src/client/components/global/i18n.ts delete mode 100644 src/client/scripts/set-i18n-contexts.ts (limited to 'src/client') diff --git a/src/client/.eslintrc b/src/client/.eslintrc index 8829472b49..5e309a95c1 100644 --- a/src/client/.eslintrc +++ b/src/client/.eslintrc @@ -1,7 +1,9 @@ { "globals": { "_DEV_": false, + "_LANG_": false, "_LANGS_": false, + "_LOCALE_": false, "_VERSION_": false, "_ENV_": false, "_PERF_PREFIX_": false, diff --git a/src/client/@types/global.d.ts b/src/client/@types/global.d.ts index 670774fdf4..a1ce02735a 100644 --- a/src/client/@types/global.d.ts +++ b/src/client/@types/global.d.ts @@ -1,4 +1,6 @@ -declare const _LANGS_: string[]; +declare const _LANG_: string; +declare const _LANGS_: string[][]; +declare const _LOCALE_: Record; declare const _VERSION_: string; declare const _ENV_: string; declare const _DEV_: boolean; diff --git a/src/client/components/abuse-report-window.vue b/src/client/components/abuse-report-window.vue index 1d87cb1802..c550e1e85d 100644 --- a/src/client/components/abuse-report-window.vue +++ b/src/client/components/abuse-report-window.vue @@ -2,11 +2,11 @@
diff --git a/src/client/components/channel-preview.vue b/src/client/components/channel-preview.vue index 41be1c296d..241fbe4f68 100644 --- a/src/client/components/channel-preview.vue +++ b/src/client/components/channel-preview.vue @@ -6,19 +6,19 @@
- + - +
- + - +
diff --git a/src/client/components/global/i18n.ts b/src/client/components/global/i18n.ts new file mode 100644 index 0000000000..603c07ca97 --- /dev/null +++ b/src/client/components/global/i18n.ts @@ -0,0 +1,15 @@ +import { h, Fragment, defineComponent } from 'vue'; +import type { SetupContext, VNodeChild, RenderFunction } from 'vue'; + +export default defineComponent({ + props: { + src: { + type: String, + required: true + }, + }, + render() { + // TODO + return h('span', this.src); + } +}); diff --git a/src/client/components/index.ts b/src/client/components/index.ts index cccb5d766a..0630ed3d8c 100644 --- a/src/client/components/index.ts +++ b/src/client/components/index.ts @@ -9,6 +9,7 @@ import userName from './global/user-name.vue'; import ellipsis from './global/ellipsis.vue'; import time from './global/time.vue'; import url from './global/url.vue'; +import i18n from './global/i18n'; import loading from './global/loading.vue'; import error from './global/error.vue'; @@ -24,4 +25,5 @@ export default function(app: App) { app.component('MkUrl', url); app.component('MkLoading', loading); app.component('MkError', error); + app.component('I18n', i18n); } diff --git a/src/client/components/note.vue b/src/client/components/note.vue index 04696b7cfa..6d5750451e 100644 --- a/src/client/components/note.vue +++ b/src/client/components/note.vue @@ -16,13 +16,13 @@
- + - +
- + - +
diff --git a/src/client/components/signup.vue b/src/client/components/signup.vue index ec631c9429..5378ec38f4 100644 --- a/src/client/components/signup.vue +++ b/src/client/components/signup.vue @@ -38,9 +38,9 @@ diff --git a/src/client/config.ts b/src/client/config.ts index d0b74be042..b9cc361cf6 100644 --- a/src/client/config.ts +++ b/src/client/config.ts @@ -1,5 +1,3 @@ -import { clientDb, entries } from './db'; - const address = new URL(location.href); const siteName = (document.querySelector('meta[property="og:site_name"]') as HTMLMetaElement)?.content; @@ -8,9 +6,9 @@ export const hostname = address.hostname; export const url = address.origin; export const apiUrl = url + '/api'; export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://') + '/streaming'; -export const lang = localStorage.getItem('lang'); +export const lang = _LANG_; export const langs = _LANGS_; -export const getLocale = async () => Object.fromEntries((await entries(clientDb.i18n)) as [string, string][]); +export const locale = _LOCALE_; export const version = _VERSION_; export const instanceName = siteName === 'Misskey' ? host : siteName; export const ui = localStorage.getItem('ui'); diff --git a/src/client/i18n.ts b/src/client/i18n.ts index 6f2dd1a7d2..ee09c4da35 100644 --- a/src/client/i18n.ts +++ b/src/client/i18n.ts @@ -1,36 +1,49 @@ -import { createI18n } from 'vue-i18n'; -import { clientDb, get, count } from './db'; -import { setI18nContexts } from '@/scripts/set-i18n-contexts'; -import { version, langs, getLocale } from '@/config'; - -let _lang = localStorage.getItem('lang'); - -if (_lang == null) { - if (langs.map(x => x[0]).includes(navigator.language)) { - _lang = navigator.language; - } else { - _lang = langs.map(x => x[0]).find(x => x.split('-')[0] == navigator.language); - - if (_lang == null) { - // Fallback - _lang = 'en-US'; +import { markRaw } from 'vue'; +import { locale } from '@/config'; + +export class I18n> { + public locale: T; + + constructor(locale: T) { + this.locale = locale; + + if (_DEV_) { + console.log('i18n', this.locale); } + + //#region BIND + this.t = this.t.bind(this); + //#endregion } - localStorage.setItem('lang', _lang); + // string にしているのは、ドット区切りでのパス指定を許可するため + // なるべくこのメソッド使うよりもlocale直接参照の方がvueのキャッシュ効いてパフォーマンスが良いかも + public t(key: string, args?: Record): string { + try { + let str = key.split('.').reduce((o, i) => o[i], this.locale) as string; + if (args) { + for (const [k, v] of Object.entries(args)) { + str = str.replace(`{${k}}`, v); + } + } + return str; + } catch (e) { + if (_DEV_) { + console.warn(`missing localization '${key}'`); + return `⚠'${key}'⚠`; + } + + return key; + } + } } -export const lang = _lang; - -export const locale = await count(clientDb.i18n).then(async n => { - if (n === 0) return await setI18nContexts(_lang, version); - if ((await get('_version_', clientDb.i18n) !== version)) return await setI18nContexts(_lang, version, true); - - return await getLocale(); -}); +export const i18n = markRaw(new I18n(locale)); -export const i18n = createI18n({ - sync: false, - locale: _lang, - messages: { [_lang]: locale } -}); +// このファイルに書きたくないけどここに書かないと何故かVeturが認識しない +declare module '@vue/runtime-core' { + interface ComponentCustomProperties { + $t: typeof i18n['t']; + $ts: typeof i18n['locale']; + } +} diff --git a/src/client/init.ts b/src/client/init.ts index 609c1086a5..c5f147ca66 100644 --- a/src/client/init.ts +++ b/src/client/init.ts @@ -40,11 +40,11 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; import widgets from '@/widgets'; import directives from '@/directives'; import components from '@/components'; -import { version, ui } from '@/config'; +import { version, ui, lang } from '@/config'; import { router } from '@/router'; import { applyTheme } from '@/scripts/theme'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode'; -import { i18n, lang } from '@/i18n'; +import { i18n } from '@/i18n'; import { stream, isMobile, dialog } from '@/os'; import * as sound from '@/scripts/sound'; import { $i, refreshAccount, login, updateAccount, signout } from '@/account'; @@ -53,6 +53,8 @@ import { fetchInstance, instance } from '@/instance'; console.info(`Misskey v${version}`); +window.clearTimeout(window.mkBootTimer); + if (_DEV_) { console.warn('Development mode!!!'); @@ -175,10 +177,11 @@ app.config.globalProperties = { $i, $store: defaultStore, $instance: instance, + $t: i18n.t, + $ts: i18n.locale, }; app.use(router); -app.use(i18n); // eslint-disable-next-line vue/component-definition-name-casing app.component('Fa', FontAwesomeIcon); diff --git a/src/client/pages/channel.vue b/src/client/pages/channel.vue index 790ad5230c..2610ab1002 100644 --- a/src/client/pages/channel.vue +++ b/src/client/pages/channel.vue @@ -10,8 +10,8 @@
diff --git a/src/client/pages/reversi/game.setting.vue b/src/client/pages/reversi/game.setting.vue index 0a98d880e7..f23a5816f2 100644 --- a/src/client/pages/reversi/game.setting.vue +++ b/src/client/pages/reversi/game.setting.vue @@ -35,18 +35,18 @@
{{ $t('random') }} - + - + - + - +
diff --git a/src/client/pages/reversi/index.vue b/src/client/pages/reversi/index.vue index 0ae0ad5a04..d57b9ae20d 100644 --- a/src/client/pages/reversi/index.vue +++ b/src/client/pages/reversi/index.vue @@ -46,11 +46,11 @@

- + - +

diff --git a/src/client/pages/settings/2fa.vue b/src/client/pages/settings/2fa.vue index 0e75382ee8..8d7a9a3832 100644 --- a/src/client/pages/settings/2fa.vue +++ b/src/client/pages/settings/2fa.vue @@ -45,14 +45,14 @@
  1. - + - +
  2. {{ $t('_2fa.step2') }}
  3. {{ $t('_2fa.step3') }}
    diff --git a/src/client/pages/settings/general.vue b/src/client/pages/settings/general.vue index 0151a29b5a..92622f4515 100644 --- a/src/client/pages/settings/general.vue +++ b/src/client/pages/settings/general.vue @@ -6,11 +6,11 @@ diff --git a/src/client/pages/timeline.tutorial.vue b/src/client/pages/timeline.tutorial.vue index f3347c1463..60e71b0979 100644 --- a/src/client/pages/timeline.tutorial.vue +++ b/src/client/pages/timeline.tutorial.vue @@ -23,14 +23,14 @@
{{ $t('_tutorial.step5_1') }}
- + - +
{{ $t('_tutorial.step5_3') }}
{{ $t('_tutorial.step5_4') }}
@@ -41,11 +41,11 @@
{{ $t('_tutorial.step7_1') }}
- + - +
{{ $t('_tutorial.step7_3') }}
diff --git a/src/client/scripts/set-i18n-contexts.ts b/src/client/scripts/set-i18n-contexts.ts deleted file mode 100644 index 6014957361..0000000000 --- a/src/client/scripts/set-i18n-contexts.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { clientDb, clear, bulkSet } from '../db'; -import { deepEntries, delimitEntry } from 'deep-entries'; - -export function setI18nContexts(lang: string, version: string, cleardb = false) { - return Promise.all([ - cleardb ? clear(clientDb.i18n) : Promise.resolve(), - fetch(`/assets/locales/${lang}.${version}.json`) - ]) - .then(([, response]) => response.json()) - .then(locale => { - const flatLocaleEntries = deepEntries(locale, delimitEntry) as [string, string][]; - bulkSet(flatLocaleEntries, clientDb.i18n); - return Object.fromEntries(flatLocaleEntries); - }); -} diff --git a/src/client/ui/deck.vue b/src/client/ui/deck.vue index 6d8fe4748e..a33e234107 100644 --- a/src/client/ui/deck.vue +++ b/src/client/ui/deck.vue @@ -177,7 +177,7 @@ export default defineComponent({ // TODO: この値を設定で変えられるようにする? $columnMargin: 12px; - $deckMargin: 12px; + $deckMargin: $columnMargin; --margin: var(--marginHalf); -- cgit v1.2.3-freya